-module(router_manager).
-include_lib("event_model.hrl").

-export([init/1, init/2]).

init(Routers)->
  run(Routers).

init(Routers, IsOneBuffer)->
  run(Routers, IsOneBuffer).

run(Routers) ->
  run(Routers, false).

run(Routers, IsOneBuffer) ->
  receive
    {From, {arrive, Packet}} ->
      #packet{plength=PLength, now_source_id=NowSID, sources=Sources, timestamps=Timestamps} = Packet,
      DestId = get_dest(NowSID, Sources),
      if
        IsOneBuffer ->
          BufferId = edm_utils:one_buffer_id();
        true ->
          BufferId = DestId
      end,
      if
        DestId=:=NowSID ->
          From ! {self(), {finish, Packet}},

          NewRouters = Routers;
        true ->
          Router = dict:fetch(NowSID, Routers),
          #router{buffers=Buffers} = Router,
          Buffer = dict:fetch(BufferId, Buffers),
          #buffer{k=K, rate=Rate, c=C} = Buffer,
          if
            K > 0 ->
              NewK = K - 1,
              %io:format("Left K:~p~n",[NewK]),
              [HTS| TTS]=Timestamps,
              #timestamp{atime=Atime} = HTS,
              WaitTime =  max(C,Atime),
              CompleteTime = WaitTime+PLength/Rate,
              NewC = CompleteTime,
              NewHTS = HTS#timestamp{wtime=WaitTime, ctime=CompleteTime},
              NewPacket = Packet#packet{timestamps=[NewHTS|TTS]},
              From ! {self(), {ok, NewPacket, WaitTime, CompleteTime}};
            true ->
              NewK = K,
              NewC = C,
              From ! {self(), {loss, Packet}}
          end,
          NewBuffer = Buffer#buffer{k=NewK, c=NewC},
          NewBuffers = dict:store(BufferId, NewBuffer, Buffers),
          NewRouter = Router#router{buffers=NewBuffers},

          NewRouters = dict:store(NowSID, NewRouter, Routers)
      end;
    {From, {leave, Packet}} ->
      #packet{now_source_id=NowSID, sources=Sources, timestamps=Timestamps} = Packet,
      [HTS|_] = Timestamps,
      #timestamp{ctime=CompleteTime} = HTS,
      NewHTS = HTS#timestamp{atime=CompleteTime},
      NewNowSID = get_dest(NowSID, Sources),
      NewPacket = Packet#packet{now_source_id=NewNowSID, timestamps=[NewHTS|Timestamps]},

      Router = dict:fetch(NowSID, Routers),
      #router{buffers=Buffers} = Router,
      DestId = get_dest(NowSID, Sources),
      if
        IsOneBuffer ->
          BufferId = edm_utils:one_buffer_id();
        true ->
          BufferId = DestId
      end,
      Buffer = dict:fetch(BufferId, Buffers),
      #buffer{k=K} = Buffer,
      NewK = K+1,
      NewBuffer = Buffer#buffer{k=NewK},
      NewBuffers = dict:store(BufferId, NewBuffer, Buffers),
      NewRouter = Router#router{buffers=NewBuffers},

      NewRouters = dict:store(NowSID, NewRouter, Routers),

      From ! {self(), {leaved, NewPacket}}
  end,
  run(NewRouters, IsOneBuffer).

get_dest(NowSID, [H|T]) ->
  case length(T) of
    0 ->
      H;
    _ ->
      if
        H=:=NowSID ->
          [NH|_] = T,
          NH;
        true ->
          get_dest(NowSID, T)
      end
  end.

